package com.xtaller.easy.admin.controller.sys;

import com.alibaba.fastjson.JSONObject;
import com.xtaller.common.convert.J;
import com.xtaller.common.convert.L;
import com.xtaller.common.convert.V;
import com.xtaller.common.convert.W;
import com.xtaller.easy.admin.base.TApi;
import com.xtaller.easy.admin.config.R;
import com.xtaller.easy.admin.model.SysRole;
import com.xtaller.easy.admin.model.SysRoleAuth;
import com.xtaller.easy.admin.model.SysRoleModule;
import com.xtaller.easy.admin.service.impl.SysMenuAuthService;
import com.xtaller.easy.admin.service.impl.SysRoleAuthService;
import com.xtaller.easy.admin.service.impl.SysRoleModuleService;
import com.xtaller.easy.admin.service.impl.SysRoleService;
import com.xtaller.easy.admin.specification.Auth;
import com.xtaller.easy.admin.specification.RoleCreate;
import com.xtaller.easy.admin.specification.RoleUpdate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Taller on 2018/5/2
 */
@Api(tags = "角色管理api")
@RestController
@RequestMapping("/v1/sys")
@CrossOrigin   //跨域服务注解
public class RoleApi extends TApi {
    @Autowired
    private SysRoleService roleService;
    @Autowired
    private SysMenuAuthService menuAuthService;
    @Autowired
    private SysRoleModuleService moduleService;
    @Autowired
    private SysRoleAuthService authService;

    private Map<String,String> RoleVerify(){
        Map<String,String> verify = new HashMap<>();
        verify.put("name","角色名称不能为空");
        return verify;
    }

    @GetMapping("/role")
    @ApiOperation(value = "读取角色数据列表")
    public Object getRole(){
        List<JSONObject> list = roleService.getRole();
        return R.ok(list);
    }

    @PostMapping("/role")
    @ApiOperation(value = "创建角色")
    public Object createRole(@RequestBody RoleCreate object){
        JSONObject check = V.checkEmpty(RoleVerify(), object);
        if(check.getBoolean("check"))
            return R.error(check.getString("message"));
        SysRole model = J.o2m(object, SysRole.class);
        model.setCreator(getUserIdByToken());
        // 名称唯一性判断
        if(roleService.existName(model, true))
            return R.error("角色名称已经存在请更换");

        model = roleService.createSysRole(model, object.getModule());
        if(model == null)
            return R.error("创建角色失败,请稍后再试");
        return R.ok("创建角色成功", formatObject(model));
    }

    @PutMapping("/role")
    @ApiOperation(value = "修改角色")
    public Object updateRole(@RequestBody RoleUpdate object){
        if(object.getId() == null)
            return R.error("数据Id不能为空");
        if(roleService.selectById(object.getId()) == null)
            return R.error("数据Id异常");
        JSONObject check = V.checkEmpty(RoleVerify(), object);
        if(check.getBoolean("check"))
            return R.error(check.getString("message"));
        SysRole model = J.o2m(object, SysRole.class);
        model.setReviser(getUserIdByToken());
        // 名称唯一性判断
        if(roleService.existName(model, false))
            return R.error("角色名称已经存在请更换");

        model = roleService.updateSysRole(model, object.getModule());
        if(model == null)
            return R.error("修改角色失败,请稍后再试");
        return R.ok("修改角色成功", formatObject(model));
    }

    @DeleteMapping("/role/{id}")
    @ApiOperation(value = "删除角色")
    public Object deleteRole(@PathVariable("id") String id){
        if(roleService.selectById(id) == null)
            return R.error("数据Id异常");
        if(roleService.getByRoleId(id).size() > 0)
            return R.error("当前角色已经分配给用户在使用,禁止直接删除。");
        if(roleService.deleteSysRole(id, getUserIdByToken()))
            return R.ok("角色删除成功");
        return R.error("删除失败请稍后再试");
    }

    @PutMapping("/role/auth/{roleId}")
    @ApiOperation(value = "配置权限")
    public Object setAuth(@PathVariable("roleId") String roleId,
                          @RequestBody List<Auth> objects){
        if(roleService.setAuth(objects, roleId, getUserIdByToken()))
            return R.ok("配置成功");
        return R.error("配置失败请稍后再试");
    }

    @GetMapping("/role/auth/{roleId}")
    @ApiOperation(value = "读取角色数据列表")
    public Object getAuthByRoleId(@PathVariable("roleId") String roleId){
        // 找到这个角色的子系统关系
        List<SysRoleModule> modules = moduleService.query(
                W.f(
                        W.and("roleId", "eq", roleId)
                ));
        if(modules.size() == 0)
            return R.error("角色尚未配置相关子系统信息");
        // 获取所有菜单数据
        List<JSONObject> data = menuService.getMenu();
        if(data.size() == 0)
            return R.error("系统尚未配置菜单或读取权限数据有误");
        // 读取该角色下所有的菜单信息
        List<SysRoleAuth> auths = authService.query(
                W.f(
                        W.and("roleId", "eq", roleId)
                )
        );
        // 拆分菜单和按钮数据源
        List<SysRoleAuth> menuAuths = new ArrayList<>();
        List<SysRoleAuth> buttonAuths = new ArrayList<>();
        if(auths.size() > 0){
            for(SysRoleAuth auth:auths){
                if(auth.getIsMenu() == 1){
                    menuAuths.add(auth);
                }else{
                    buttonAuths.add(auth);
                }
            }
        }
        // 数据组合整理
        List<JSONObject> menus = new ArrayList<>();
        for(JSONObject item:data){
            List<JSONObject> ms = J.o2l(item.get("menus"));
            if(ms.size() > 0){
                for(JSONObject m:ms){
                    // 处理菜单
                    m.put("checked", false);
                    if(menuAuths.size() > 0){
                        for(SysRoleAuth ma:menuAuths){
                            if(V.isEqual(ma.getMenuId(), m.getString("id")) &&
                                    ma.getIsMenu() == 1){
                                m.put("checked", true);
                            }
                        }
                    }
                    // 处理按钮
                    List<JSONObject> btns = J.o2l(m.get("btns"));
                    if(btns.size() > 0){
                        for(JSONObject b:btns){
                            b.put("checked", false);
                            for(SysRoleAuth ba:buttonAuths){
                                if(V.isEqual(ba.getMenuId(), b.getString("menuId")) &&
                                        V.isEqual(ba.getAuthId(), b.getString("id")) &&
                                        ba.getIsMenu() == 0){
                                    b.put("checked", true);
                                }
                            }
                        }
                    }
                    m.put("btns", btns);
                }
            }
            item.put("menus", L.list2Tree(ms, "0"));
        }
        for(SysRoleModule module:modules){
            for(JSONObject item:data){
                if(V.isEqual(module.getModuleId(), item.getString("id"))){
                    menus.add(item);
                }
            }
        }
        return R.ok(menus);
    }
}
